<?php
/**
 * Created by PhpStorm.
 * User: lulan
 * Date: 2016/1/13
 * Time: 10:09
 */
class Connection{

    /**
     * @var PDO
     */
    public $pdo = [];//PDO
    public $config = [];
    public $database = [];
    public $lastInsertId;
    public $prefix = [];
    public $driver;
    public $error;
    public $rowCount = 0;
    public $inTransaction = false;

    public function __construct(array $config=[]){
        //读
        $read_config = isset($config['read']) ? $config['read'] : [];
        $read_config = !empty($read_config) ? $read_config : (isset($config['default']) ? $config['default'] : []);
        $read_config = !empty($read_config) ? $read_config : (!empty($config) ? $config : die('wrong config'));
        //写
        $write_config = isset($config['write']) ? $config['write'] : [];
        $write_config = !empty($write_config) ? $write_config : (isset($config['default']) ? $config['default'] : []);
        $write_config = !empty($write_config) ? $write_config : (!empty($config) ? $config : die('wrong config'));
        //连接数据库
        $this->connect($read_config, 'read');
        $this->connect($write_config, 'write');
    }

    public function connect(array $config=[], $type){
        $this->config[$type] = $config;
        $this->driver = isset($config["driver"]) ? $config["driver"] : "mysql";
        $this->database[$type] = isset($config["database"]) ? $config["database"] : "z_db";
        $this->prefix[$type] = isset($config["prefix"]) ? $config["prefix"] : "db_";
        $username = isset($config["user"]) ? $config["user"] : $this->database[$type];
        $password = isset($config["pass"]) ? $config["pass"] : "";
        $host = isset($config["host"]) ? $config["host"] : "127.0.0.1";
        $port = isset($config["port"]) ? $config["port"] : "3306";
        $charset = isset($config["charset"]) ? $config["charset"] : "utf8";
        //暂时只测试了Mysql数据库引擎
        switch($this->driver){
            case "mssql" :
                $dns = "odbc:Driver={SQL Server};Server={$host},{$port};Database={$this->database[$type]};";
                break;
            case "sqlite" :
                $dns = "sqlite:{$this->database[$type]}";
                break;
            case "oracle" :
                $dns = "oci:dbname={$this->database[$type]}";
                break;
            case "mysql" :
                $dns = "mysql:host={$host};port={$port};dbname={$this->database[$type]}";
                break;
            default :
                throw new PDOException("error DNS", 38);
                break;
        }
        //开始连接数据库
        try{
            $this->pdo[$type] = new PDO($dns, $username, $password,
                array(
                    PDO::ATTR_PERSISTENT => 1,
                    PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES '{$charset}';"
                )
            );
            //在默认情况下，PDO并没有让MySQL数据库执行真正的预处理语句。为了解决这个问题，要禁止模拟预处理语句！
            $this->pdo[$type]->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);//禁止PDO模拟预处理语句
            $this->pdo[$type]->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);//这个不是必须的，但是建议加上，这样在脚本出错时，不会停止运行，而是会抛出异常！
        }catch (PDOException $e){
            $this->connectFail($e);
        }
    }

    private function connectFail(PDOException $e){
        exit($e->getMessage());
    }

    /**
     * @param string $type
     * @return PDO
     */
    public function getPdo($type='read'){
        return $this->pdo[$type];
    }

    /**
     * 重新连接数据库
     */
    public function reConnect(){
        $this->connect($this->config['read']);
        $this->connect($this->config['write']);
    }

    /**
     * 开始事务，这一个事务开始后，需要手动提交或者回滚，否则Query里边的事务不会开始，也不会提交，更不会有回滚
     */
    public function beginTransaction(){
        if(!$this->inTransaction){
            $this->pdo["write"]->beginTransaction();
            $this->inTransaction = true;
        }
    }

    /**
     * 事务提交
     */
    public function commit(){
        if($this->inTransaction){
            $this->pdo["write"]->commit();
        }
        $this->inTransaction = false;
    }

    /**
     * 事务回滚
     */
    public function rollBack(){
        if($this->inTransaction){
            $this->pdo["write"]->rollBack();
        }
        $this->inTransaction = false;
    }
}